﻿
using Microsoft.LightSwitch.ApplicationInfrastructure.Utilities.Internal;
using Microsoft.LightSwitch.Presentation.Utilities.Internal;
using Microsoft.LightSwitch.Runtime.Shell.Implementation.Standard;
using Microsoft.LightSwitch.Runtime.Shell.ViewModels.Commands;
using Microsoft.LightSwitch.SilverlightUtilities.Controls.Internal;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
namespace LightSwitchApplication
{
    public class MyCommandsView : UserControl
    {
        internal BusyIndicator _busyIndicator;
        private bool _contentLoaded;
        private static BitmapImage _defaultButtonImage;
        private ICommandsViewModel _viewModel;
        private const string CompactSizeRibbonButtonStyle = "CompactSizeRibbonButtonStyle";
        private const string CompressedRibbonButtonStyle = "CompressedRibbonButtonStyle";
        private const int CompressStyleMarginHeight = 0x19;
        private const string FullSizeRibbonButtonStyle = "FullSizeRibbonButtonStyle";
        private const int FullSizeStyleMarginAndImageHeight = 50;
        internal RibbonCommandBar HomeTabItem;
        private static bool Initialized = false;
        public static readonly DependencyProperty IsCompressedViewProperty = DependencyProperty.Register("IsCompressedView", typeof(bool), typeof(CommandsView), new PropertyMetadata(false, new PropertyChangedCallback(MyCommandsView.OnIsCompressedViewChanged)));
        internal Grid LayoutRoot;

        public MyCommandsView()
        {
            this.InitializeComponent();
            base.Loaded += new RoutedEventHandler(this.CommandsView_Loaded);
            Binding binding = new Binding("IsCompressed")
            {
                Source = this.HomeTabItem
            };
            base.SetBinding(IsCompressedViewProperty, binding);
        }

        private void _viewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("ShellCommandGroups", StringComparison.Ordinal))
            {
                this.RefreshButtons();
            }
        }

        private void CommandsView_Loaded(object sender, RoutedEventArgs e)
        {
            if (!Initialized)
            {
                this._viewModel = (ICommandsViewModel)base.DataContext;
                this._viewModel.PropertyChanged += new PropertyChangedEventHandler(this._viewModel_PropertyChanged);
                this.RefreshButtons();
                Initialized = true;
            }
        }

        private RibbonGroup CreateRibbonGroup(IShellCommandGroup commandGroup)
        {
            RibbonGroup group = new RibbonGroup
            {
                Header = string.IsNullOrEmpty(commandGroup.DisplayName) ? commandGroup.Name : commandGroup.DisplayName,
                IsTabStop = false,
                HorizontalAlignment = this.GetGroupAlignment(commandGroup.Name),
                IsCompressed = this.IsCompressedView
            };
            foreach (IShellCommand command in commandGroup.Commands)
            {
                if (command != null)
                {
                    RibbonButton item = new RibbonButton
                    {
                        DataContext = command
                    };
                    item.SetBinding(RibbonButton.HeaderProperty, new Binding("DisplayName"));
                    item.SetBinding(RibbonButton.ToolTipProperty, new Binding("Description"));
                    var instance=GetField<BooleanToVisibleConverter>(typeof(BooleanToVisibleConverter),"Instance");
                    Binding binding = new Binding("IsVisible")
                    {                        
                        Converter = instance
                    };
                    item.SetBinding(UIElement.VisibilityProperty, binding);
                    item.SetBinding(AutomationProperties.HelpTextProperty, new Binding("Description"));
                    if (command.Image != null)
                    {
                        item.SetBinding(RibbonButton.ButtonImageSourceProperty, new Binding("Image"));
                    }
                    else
                    {
                        item.ButtonImageSource = this.DefaultButtonImage;
                    }
                    item.Style = this.GetButtonStyle(command);
                    group.Items.Add(item);
                }
            }
            return group;
        }

        private Style GetButtonStyle(IShellCommand command)
        {
            if (this.IsCompressedView)
            {
                return (Style)base.Resources["CompressedRibbonButtonStyle"];
            }
            if (command.ShowSmallImage)
            {
                return (Style)base.Resources["CompactSizeRibbonButtonStyle"];
            }
            return (Style)base.Resources["FullSizeRibbonButtonStyle"];
        }

        private HorizontalAlignment GetGroupAlignment(string groupName)
        {
            if (string.Equals(groupName, ShellCommandGroupNames.Customize, StringComparison.OrdinalIgnoreCase))
            {
                return HorizontalAlignment.Right;
            }
            return HorizontalAlignment.Left;
        }

        [DebuggerNonUserCode]
        public void InitializeComponent()
        {
            if (!this._contentLoaded)
            {
                this._contentLoaded = true;
                System.Windows.Application.LoadComponent(this, new Uri("/Microsoft.LightSwitch.Client.Internal;component/RuntimeApplication/StandardShell/Implementations/Views/Commands/CommandsView.xaml", UriKind.RelativeOrAbsolute));
                this.LayoutRoot = (Grid)base.FindName("LayoutRoot");
                this.HomeTabItem = (RibbonCommandBar)base.FindName("HomeTabItem");
                this._busyIndicator = (BusyIndicator)base.FindName("_busyIndicator");
            }
        }

        private static void OnIsCompressedViewChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((MyCommandsView)obj).RefreshButtons();
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if ((Keyboard.Modifiers == ModifierKeys.None) && ((e.Key == Key.Right) || (e.Key == Key.Left)))
            {
                Func<RibbonGroup, bool> predicate = null;
                Control focusedElement = FocusManager.GetFocusedElement() as Control;
                if (focusedElement != null)
                {
                    if (predicate == null)
                    {
                        predicate = g => g.Items.FirstOrDefault<FrameworkElement>(i => (i.DataContext == focusedElement.DataContext)) != null;
                    }
                    RibbonGroup item = this.HomeTabItem.Groups.FirstOrDefault<RibbonGroup>(predicate);
                    int index = this.HomeTabItem.Groups.IndexOf(item);
                    int num2 = -1;
                    if (e.Key == Key.Right)
                    {
                        if (this.HomeTabItem.Groups.Count > (index + 1))
                        {
                            num2 = index + 1;
                        }
                    }
                    else if ((e.Key == Key.Left) && (index > 0))
                    {
                        num2 = index - 1;
                    }
                    if (num2 != -1)
                    {
                        RibbonGroup group2 = this.HomeTabItem.Groups[num2];
                        if (group2 != null)
                        {
                            if (e.Key == Key.Left)
                            {
                                group2.SetFocusOnLastItem();
                            }
                            else
                            {
                                group2.SetFocusOnFirstItem();
                            }
                        }
                        e.Handled = true;
                    }
                }
            }
        }

        private void RefreshButtons()
        {
            foreach (RibbonGroup group in this.HomeTabItem.Groups)
            {
                foreach (FrameworkElement element in group.Items)
                {
                    element.DataContext = null;
                }
            }
            this.HomeTabItem.Groups.Clear();
            if (this._viewModel != null)
            {
                foreach (IShellCommandGroup group2 in this._viewModel.ShellCommandGroups)
                {
                    RibbonGroup item = this.CreateRibbonGroup(group2);
                    if (item.Items.Count > 0)
                    {
                        this.HomeTabItem.Groups.Add(item);
                    }
                }
            }
            TextBlock block = new TextBlock
            {
                FontFamily = base.FontFamily,
                FontSize = base.FontSize,
                FontWeight = base.FontWeight,
                Text = "Dummy"
            };
            if (this.IsCompressedView)
            {
                base.MaxHeight = block.ActualHeight + 25.0;
            }
            else
            {
                base.MaxHeight = (block.ActualHeight * 3.0) + 50.0;
            }
        }

        private BitmapImage DefaultButtonImage
        {
            get
            {
                if (_defaultButtonImage == null)
                {
                    _defaultButtonImage = new BitmapImage();
                    StreamResourceInfo resourceStream = System.Windows.Application.GetResourceStream(ResourceUtilities.GetUri("runtimeapplication/standardshell/implementations/resources/Placeholder_32x32.png"));
                    _defaultButtonImage.SetSource(resourceStream.Stream);
                }
                return _defaultButtonImage;
            }
        }

        public bool IsCompressedView
        {
            get
            {
                return (bool)base.GetValue(IsCompressedViewProperty);
            }
            set
            {
                base.SetValue(IsCompressedViewProperty, value);
            }
        }


        #region Reflection

        public static void setField(Type type, string fieldName, object o, object value)
        {
            FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
            fi.SetValue(o, value);
        }

        public static void setField(string fieldName, object o, object value)
        {
            setField(o.GetType(), fieldName, o, value);
        }

        public static T getField<T>(Type type, string fieldName, object o)
        {
            T result = default(T);

            FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
            result = (T)fi.GetValue(o);

            return result;
        }

        public static T getField<T>(string fieldName, object o)
        {
            return getField<T>(o.GetType(), fieldName, o);
        }

        public static T GetField<T>(Type type, string fieldName)
        {
            T result = default(T);

            FieldInfo fi = type.GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic);
            result = (T)fi.GetValue(null);

            return result;
        }
        /// <summary>
        /// 获取反射的属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        public static T getPerperty<T>(string property, object o)
        {
            T result;

            Type t = o.GetType();

            PropertyInfo pi = t.GetProperty(property, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic);
            result = (T)pi.GetValue(o, null);

            return result;
        }

        public static void setPerperty(string property, object o, object value, object[] index)
        {

            Type t = o.GetType();

            PropertyInfo pi = t.GetProperty(property, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetProperty);
            pi.SetValue(o, value, index);

        }

        public static object InvokeMethod(object target, string methodName, object[] parameters)
        {
            return InvokeMethod(target.GetType(), target, methodName, parameters);
        }

        /// <summary>
        /// 反射调用非重载方法
        /// </summary>
        /// <param name="t"></param>
        /// <param name="target"></param>
        /// <param name="methodName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static object InvokeMethod(Type t, object target, string methodName, object[] parameters)
        {
            MethodInfo method = null;
            if (target == null)
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
            }
            else
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            }
            var result = method.Invoke(target, parameters);
            return result;
        }

        /// <summary>
        /// 反射调用重载的方法
        /// </summary>
        /// <param name="t"></param>
        /// <param name="target"></param>
        /// <param name="methodName"></param>
        /// <param name="parameters"></param>
        /// <param name="parameterTypes"></param>
        /// <returns></returns>
        public static object InvokeMethod(Type t, object target, string methodName, object[] parameters, Type[] parameterTypes)
        {
            MethodInfo method = null;
            if (target == null)
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, Type.DefaultBinder, parameterTypes, null);
            }
            else
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder, parameterTypes, null);
            }
            var result = method.Invoke(target, parameters);
            return result;
        }

        #endregion
    }
}
